/*-------------------------------------
	       Admin 2010
	    By Scooby, 2010
-------------------------------------*/

require( "glon" )

spl = {}
spl.red = Color( 255, 12, 23, 255 )
spl.green = Color( 40, 255, 12, 255 )
spl.blue = Color( 40, 20, 255, 255 )
spl.white = color_white
spl.black = color_black
spl.fnp = "No Players Found!"
spl.fmp = "More Than One Player Found!" 

hook.Add( "Initialize", "sPlugin_Init", function()
	if( CLIENT ) then
		Msg( "== Admin 2010 Client Side Started ==\n" )
	else
		spl:LoadInfo()
	end
	spl:LoadPlugins()
end )

if( SERVER ) then

function spl:LoadInfo()
	if( file.Exists( "sPlugins.txt" ) ) then
		self.info = glon.decode( file.Read( "sPlugins.txt" ) )
	else
		self.info = {}
	end
	if( file.Exists( "sGroups.txt" ) ) then
		self.groups = glon.decode( file.Read( "sGroups.txt" ) )
	end
end

function spl:SaveInfo()
	file.Write( "sPlugins.txt", glon.encode( self.info ) )
	file.Write( "sGroups.txt", glon.encode( self.groups ) )
end

hook.Add( "Initialize", "sPluginServCall", function()
	timer.Simple( 0.1, function()
		spl:CallFunc( "Init" )
	end )
end )

end

/*---------------------------------
	Utility Functions
---------------------------------*/

function spl:FindPly( str )

	local res = {}
	
	for _,v in ipairs( player.GetAll() ) do
		
		if( string.find( string.lower( v:Nick() ), string.lower( str ) ) ) then
			table.insert( res, v )
		end
		
	end
	
	return res
	
end
			

function spl:pack( ... )
	return args
end

/*---------------------------------
	  Colored Chat
---------------------------------*/

if( SERVER ) then

	function spl:PrintC( ... )
	local rec = RecipientFilter()
	if( type( arg[1] ) != "Player"  ) then
		rec:AddAllPlayers()
	elseif( type( arg[1] ) == "Entity" ) then
		print( unpack( args ) )
	else
		rec:AddPlayer( arg[1] )
	end
	table.insert( arg, 1, Color( 255, 255, 255, 255 ) )
	table.insert( arg, 2, "[Admin] " )
	umsg.Start( "Spl_ColMes", rec )
	umsg.Short( #arg + 2 )
	
		for _,v in ipairs( arg ) do
			if( type( v ) == "string" ) then
				umsg.String( v )
			elseif( type( v ) == "table" ) then
				umsg.Short( v.r )
				umsg.Short( v.g )
				umsg.Short( v.b )
				umsg.Short( v.a )
			end
		end
		umsg.End()
	end

else

	usermessage.Hook( "Spl_ColMes", function( um )
		local argc = um:ReadShort()
		local args = {}
		for i = 1, argc/2, 1 do
			table.insert( args, Color( um:ReadShort(), um:ReadShort(), um:ReadShort(), um:ReadShort() ) )
			table.insert( args, um:ReadString() )
		end
		chat.AddText( unpack( args ) )
	end)
	
end

/*---------------------------------
	  Plugin Managment
---------------------------------*/

function spl:AddPlugin( tbl )
	table.insert( self.plugins, tbl )
end

function spl:CheckMount( str )
	if( !self.info.Mplugins[ str ] ) then 
		self.info.Mplugins[ str ] = true
		return true
	end
	for k,v in pairs( self.info.Mplugins ) do
		if( string.lower( k ) == string.lower( str ) ) then
			return v
		end
	end
end

function spl:LoadPlugins()
	spl.plugins = {}
	//if( !spl.info.Mplugins ) then spl.info.Mplugins = {} end -- Plugins Mounted
	//if( !spl.info.Uplugins ) then spl.info.Uplugins = {} end -- Plugins Unmounted
	local plugins = file.FindInLua( "splugins/*.lua" )
	for _,v in ipairs( plugins ) do
		//if( spl:CheckMount( v ) ) then
			local pre = string.Left( v, string.find( v, "_" ) - 1 )
			if( CLIENT ) then
				if ( pre == "cl" or pre == "sh" ) then
					include( "splugins/"..v )
				end
			elseif( SERVER ) then
				if( pre == "sh" or pre == "cl" ) then
					AddCSLuaFile( "splugins/"..v )
				end
				if( pre == "sh" or pre == "sv" ) then
					include( "splugins/"..v )
				end
			end
		//end
	end
end

/*---------------------------------
	Calling Functions
---------------------------------*/

function spl:CallFunc( str, ... ) -- Calls A Function Inside Of A Plugin( ex.     PLUGIN:Init   would be called by spl:CallFunc( "Init" )  )
	local tbl = spl.plugins
	for _,a in pairs( tbl ) do
		for k,v in pairs( a ) do
			if( string.lower( k ) == string.lower( str ) ) then
				if( arg ) then
					pcall( v, unpack( arg ) )
				else
					pcall( v )
				end
			end
		end
	end
end

/*---------------------------------
      ConCommand Utilities
---------------------------------*/

function spl:ReviseArg( tbl )

	if( !tbl ) then return false end
	local ret = tbl[1]
	table.remove( tbl, 1 )
	return ret
	
end

/*---------------------------------
	     Groups
---------------------------------*/

if( SERVER ) then

function spl:RegisterGroup( tbl )

	if( !spl.groups ) then spl.groups = {} end
	
	table.insert( spl.groups, tbl )
	
	spl:SaveInfo()
	
end

function _R.Player:Spl_SetP( str, strr )

	if( !spl.info.p ) then spl.info.p = {} end
	
	if( !spl.info.p[ self:SteamID() ] ) then spl.info.p[ self:SteamID() ] = {} end
	
	spl.info.p[ self:SteamID() ] [ str ] = strr
	
	spl:SaveInfo()
end

function _R.Player:Spl_GetP( str, def )

	if( !spl.info.p ) then return def end
	
	if( !spl.info.p[ self:SteamID() ] ) then return def end
	
	if( !spl.info.p[ self:SteamID() ] [ str ] ) then return def end
	
	return spl.info.p[ self:SteamID() ] [ str ]
	
end

function _R.Player:SetSplGroup( str, me )
	if( spl:IsGroup( str ) ) then
		self:Spl_SetP( "group", str )
		spl:PrintC( spl.blue, self:Nick().." Was Added To '"..str.."' By "..me:Nick() )
	else
		spl:PrintC( me, spl.red, "Sorry "..str.." Is Not A Valid Group" )
	end
end

function _R.Player:CanSplDo( ply )

	if( !self:IsValid() ) then return true end -- Console
	if( self == ply ) then return true end
	if( self:GetSplGroup() == ply:GetSplGroup() and self:IsSplLeader( self:GetGroup() ) ) then return true end
	return ( self:GetSplLevel() > ply:GetSplLevel() )
	
end

function spl:GroupExists( str )

	if( !spl.groups ) then return false end
	
	for a,b in pairs( spl.groups ) do
		if( string.lower( b[ "Name" ] ) == string.lower( str ) ) then
			return true 
		end
	end
	
end


function spl:GetLevel( str )
	
	for a,b in pairs( spl.groups ) do
		if( string.lower( b[ "Name" ] ) == string.lower( str ) ) then
			return tonumber( v[ "Rank" ] )
		end
	end
	
end

function _R.Player:GetSplLevel()

	local gr = self:GetSplGroup()
	
	if( !spl.groups ) then return 999 end
	
	for a,b in pairs( spl.groups ) do
		if( string.lower( b[ "Name" ] ) == string.lower( gr ) ) then
			return tonumber( b[ "Rank" ] )
		end
	end
	
end

function spl:GetBestGroup()
	
	local tmp = {}
	for a,b in pairs( spl.groups ) do
		tmp[ b[ "Name" ] ] = b[ "Rank" ]
	end
	table.sort( tmp, function( a, b ) return a < b end )
	return tmp[1]
end

function _R.Player:GetSplGroup()
	
	return self:Spl_GetP( "group", "Guest" )
	
end

function spl:IsGroup( str ) 
	
	return spl:GroupExists( str )
	
end

end

/*---------------------------------
     Main Console Command
---------------------------------*/

concommand.Add( "admin", function( ply, com, args ) -- This Is Almost the Same As The Chat Just Tweaked For Console! 
	
	if( #args == 0 ) then return end
	
		local com = spl:ReviseArg( args )
		for k,v in ipairs( spl.plugins ) do
		
			if( v[ "Command" ] != nil ) then
				if( string.lower( v[ "Command" ] ) == string.lower( com ) ) then
					if( v[ "Format" ] ) then
						local form = string.Explode( " ", v[ "Format" ] )
						if( #form > #args ) then
							if( v[ "Use" ] ) then
								spl:PrintC( ply, spl.red, "Invalid Format ( admin "..v[ "Command" ].." "..v[ "Use" ].." )" )
							end
							return false
						else
							for i=1, #args do
								if( form[i] == "number" ) then
									if( !tonumber( args[i] ) or args[i] == nil ) then
										if( v[ "Use" ] ) then
											spl:PrintC( ply, spl.red, "Invalid Format ( admin "..v[ "Command" ].." "..v[ "Use" ]..")" )
										end
										return false
									end
								elseif( form[i] == "string" ) then
									if( !tostring( args[i] ) or args[i] == nil ) then
										if( v[ "Use" ] ) then
											spl:PrintC( ply, spl.red, "Invalid Format ( admin "..v[ "Command" ].." "..v[ "Use" ]..")" )
										end
									return false
									end
								end
							end
						
						end
					end
					if( v[ "Group" ] < ply:GetSplLevel() and !ply:IsListenServerHost() ) then
						spl:PrintC( ply, spl.red, "You Do Not Have Acess To This Command" )
					else
						pcall( v[ "Main" ], " ", ply, args )
					end
				end
			end
		
		end
	
end )

/*---------------------------------
	     Other
---------------------------------*/
if( SERVER ) then

function _R.Player:IsAdmin()
	return ( self:GetSplLevel() >= spl.info.alevel )
end

function _R.Player:IsSuperAdmin()
	return ( self:GetSplLevel() >= spl.info.salevel )
end

function _R.Entity:Nick() if( !self:IsValid() ) then return "Console" end end
function _R.Entity:GetSplLevel() if( !self:IsValid() ) then return -1 end end
function _R.Entity:CanSplDo( null ) if( !self:IsValid() ) then return true end end
function _R.Entity:GetSplLevel() if( !self:IsValid() ) then return spl:GetBestGroup() end end
function _R.Entity:IsAdmin() if( !self:IsValid() ) then return true end end
function _R.Entity:IsSuperAdmin() if( !self:IsValid() ) then return true end end

end

/*---------------------------------
	Group Leader
---------------------------------

if( SERVER ) then

function _R.Player:SetAsSplLeader( str, me )
	
	if( spl:GroupExists( str ) ) then
		if( spl:GetLeader( str ) ) then
			local old = spl:GetLeader( str )
		end
		for k,v in pairs( spl.groups ) do
			if( string.lower( v[ "Name" ] ) == string.lower( str ) ) then
				v[ "Leader" ] = self:SteamID()
			end
		end
		spl:SaveInfo()
		spl:PrintC( spl.blue, me:Nick().." Has Set "..self:Nick().." As Group Leader Of "..str.."'s" )
	else
		spl:PrintC( me, spl.red, "That Group Does Not Exist" )
	end
end

function spl:GetLeader( str ) 
	if( spl:GroupExists( str )) then
		for _,v in pairs( spl.groups ) do
			if( string.lower( v[ "Name" ] ) == string.lower( str ) ) then
				if( v[ "Leader" ] ) then return v[ "Leader" ] end
			end
		end
	end
end

---------------------
    Chat Cmds
--------------------*/
if( SERVER ) then

function spl.CheckChat( ply, str, team, dead )

	local pre = string.Left( str, 1 )
	if( pre == "!" or pre == "@" or pre == "#" ) then
		spl:ChatCmd( ply, string.Explode( " ", string.lower( string.Right( str, string.len( str ) - 1 ) ) ) )
		return spl.info.hidechat or false
	else
		return str
	end
end
hook.Add( "PlayerSay", "AdminCheckText", spl.CheckChat )

end

function spl:ChatCmd( ply, args )
	
	
	if( args ) then
		local com = spl:ReviseArg( args )
		for k,v in ipairs( spl.plugins ) do
		
			if( v[ "Command" ] != nil ) then
				if( string.lower( v[ "Command" ] ) == string.lower( com ) ) then
					if( v[ "Format" ] ) then
					local form = string.Explode( " ", v[ "Format" ] )
					if( #form > #args ) then
						if( v[ "Use" ] ) then
							spl:PrintC( ply, spl.red, "Invalid Format ( !"..v[ "Command" ].." "..v[ "Use" ].." )" )
						end
						return false
					else
						for i=1, #args do
							if( form[i] == "number" ) then
									if( !tonumber( args[i] ) or args[i] == nil ) then
									if( v[ "Use" ] ) then
										spl:PrintC( ply, spl.red, "Invalid Format ( !"..v[ "Command" ].." "..v[ "Use" ]..")" )
									end
									return false
								end
							elseif( form[i] == "string" ) then
								if( !tostring( args[i] ) or args[i] == nil ) then
									if( v[ "Use" ] ) then
										spl:PrintC( ply, spl.red, "Invalid Format ( !"..v[ "Command" ].." "..v[ "Use" ]..")" )
									end
									return false
								end
								end
							end
						
						end
					end
		
					if( v[ "Group" ] < ply:GetSplLevel() and !ply:IsListenServerHost() ) then
						spl:PrintC( ply, spl.red, "You Do Not Have Acess To This Command" )
					else
						pcall( v[ "Main" ], " ", ply, args )
					end
					return true
				end
			end
		
		end
	end
	
	spl:PrintC( ply, spl.red, "Unkown Command" )
	
end


/*--------------------------
	Noclip
---------------------------*/

function spl.DenyClip( ply )
	
	hook.Add( "PlayerNoClip", "Admin2010_Deny_"..ply:SteamID(), function( pl )
		if( ply == pl ) then return false end
	end)
	
end

function spl.AllowClip( ply )
	
	hook.Remove( "PlayerNoClip", "Admin2010_Deny_"..ply:SteamID() )

end